package cate.game.rank.cross.h;

import cate.common.table.d.GDRank;
import cate.common.util.GameResult;
import cate.game.rank.cross.CrossRankMessageModule;
import cate.game.rank.cross.CrossRankMessageModule.CrossRankRoleGetListResp;
import cate.game.rank.h.IConditionRankHandler;
import cate.game.rank.msg.SingleRankDataResp;
import cate.game.rank.po.Rank;
import cate.game.role.Role;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 跨服排行处理
 */
public abstract class BaseCrossRankLoader implements IConditionRankHandler {
    @Getter
    int rankId;
    /**
     * 缓存的排行列表
     */
    List<Rank> cachedRankList;
    /**
     * 上次加载时间
     */
    long lastLoadTime;

    CrossRankMessageModule messageModule;

    UpdateType updateType;

    public BaseCrossRankLoader() {

    }

    public BaseCrossRankLoader(int rankId) {
        this(null, rankId);
    }

    public BaseCrossRankLoader(CrossRankMessageModule messageModule, int rankId) {
        this(messageModule, rankId, UpdateType.REAL_TIME);
    }

    public BaseCrossRankLoader(CrossRankMessageModule messageModule, int rankId, UpdateType updateType) {
        this.messageModule = messageModule;
        this.rankId = rankId;
        this.updateType = updateType;
    }

    private CrossRankMessageModule getMessageModule(Role role) {
        if (messageModule != null) {
            return messageModule;
        }
        return role.getGame().crossRank.getMessageModule();
    }


    /**
     * 刷新记录
     *
     * @param role 角色
     * @param newValue 新数值
     */
    public void record(Role role, long newValue, boolean force) {
        if (force || updateType == UpdateType.REAL_TIME) {
            updateRole(role, newValue);
        }
    }

    public void updateRole(Role role, long newValue) {
        if (getConditionValue() > newValue) {
            return;
        }
        getMessageModule(role).updateRoleRecord(role, rankId, newValue);
    }

    public void updateRole(Role role, long newValue, long extraValue) {
        if (getConditionValue() > newValue) {
            return;
        }
        getMessageModule(role).updateRoleRecord(role, rankId, newValue, extraValue);
    }

    /**
     * 发送跨服排行数据
     *
     * @param role 角色
     * @param limit 限制
     */
    public GameResult<Void> sendCrossRankList(Role role, int limit) {
        GameResult<Void> r = new GameResult<>();
        long nowTime = System.currentTimeMillis();
        boolean forceLoad = CollectionUtils.isEmpty(cachedRankList)
                || limit > cachedRankList.size()
                || cachedRankList.stream().anyMatch(rank -> StringUtils.equals(role.getUid(), rank.owner.uid))
                || nowTime - lastLoadTime >= GDRank.CROSS_RANK_CACHE_TIME_MILLIS;
        if (updateType == UpdateType.SPECIFIC_TIME) {
            updateRole(role, getRoleCurrentValue(role), getRoleCurrentExtraValue(role));
        }
        CrossRankRoleGetListResp res = getMessageModule(role).getRoleRankList(role, rankId, limit, forceLoad);
        if (!res.ok()) {
            return r.fail(res.ec, res.em);
        }
        if (res.list != null) {
            cachedRankList = res.list;
            lastLoadTime = nowTime;
        }
        List<Rank> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(cachedRankList)) {
            if (limit >= cachedRankList.size()) {
                list.addAll(cachedRankList);
            } else {
                list.addAll(cachedRankList.subList(0, limit));
            }
        }
        Rank self = Optional.ofNullable(res.self).orElse(new Rank(role, getRoleCurrentValue(role)));
        role.sendNow(new SingleRankDataResp(rankId, res.myRank, self, list, 0));
        return r.success();
    }

    enum UpdateType{
        /** 实时更新 */
        REAL_TIME,
        /** 特定更新（上下线+查询排行榜） */
        SPECIFIC_TIME
    }
}
